<!DOCTYPE html>


<html lang="zh-Hans">
  

    <head>
      <meta charset="utf-8" />
       
      <meta name="keywords" content="前端，思考，感悟，代码，博客" />
       
      <meta name="description" content="向来缘浅，奈何情深。" />
      
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1"
      />
      <title>从输入URL到页面展示发生了什么 |  飞蓬</title>
  <meta name="generator" content="hexo-theme-ayer">
      
      <link rel="shortcut icon" href="/favicon.ico" />
       
<link rel="stylesheet" href="/dist/main.css">

      
<link rel="stylesheet" href="/css/fonts/remixicon.css">

      
<link rel="stylesheet" href="/css/custom.css">
 
      <script src="https://cdn.staticfile.org/pace/1.2.4/pace.min.js"></script>
       
 

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-bulma@5.0.1/bulma.min.css"
      />
      <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.js"></script>

      <!-- mermaid -->
      
      <style>
        .swal2-styled.swal2-confirm {
          font-size: 1.6rem;
        }
      </style>
    </head>
  </html>
</html>


<body>
  <div id="app">
    
      
    <main class="content on">
      <section class="outer">
  <article
  id="post-page4"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  从输入URL到页面展示发生了什么
</h1>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2023/03/11/page4/" class="article-date">
  <time datetime="2023-03-11T13:56:01.000Z" itemprop="datePublished">2023-03-11</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95/">前端面试</a>
  </div>
  
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> Word count:</span>
            <span class="post-count">4.1k</span>
        </span>
    </span>

    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> Reading time≈</span>
            <span class="post-count">14 min</span>
        </span>
    </span>
</div>
 
    </div>
      
    <div class="tocbot"></div>




  
    <div class="article-entry" itemprop="articleBody">
       
  <p>在浏览器地址栏输入网址，如：<a target="_blank" rel="noopener" href="https://www.baidu.com/">www.baidu.com</a>后浏览器是怎么把最终的页面呈现出来的呢？</p>
<span id="more"></span>

<ol>
<li>浏览器输入URL地址按下回车</li>
<li>浏览器查找当前URL是否存在缓存，并比较缓存是否过期</li>
<li>DNS解析URL对应的IP</li>
<li>根据IP建立TCP链接（三次握手）</li>
<li>HTTP发起请求</li>
<li>服务器处理请求，浏览器接收HTTP响应</li>
<li>渲染页面，构建DOM树</li>
<li>关闭TCP链接（四次握手）</li>
</ol>
<h3 id="一、URL"><a href="#一、URL" class="headerlink" title="一、URL"></a>一、URL</h3><p>URL（Uniform Resource Locator），统一资源定位符，用于定位互联网上资源，俗称网址。URL中的所有字符都是<em>ASCII</em>字符集，如果出现非<em>ASCII</em>字符，比如中文，浏览器会进行编码再进行传输</p>
<p>遵守以下的语法规则：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">scheme</span>:<span class="comment">//host:port/path/filename</span></span><br><span class="line"><span class="attr">https</span>:<span class="comment">//www.baidu.com:443/img?name=123#anchor</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>scheme（协议）：因特网服务的类型。常见的协议有 http、https、ftp、file。http最常见，https 是进行加密的网络传输。</p>
</li>
<li><p>host（主机名，域名，IP）</p>
</li>
<li><p>port（端口号）：整数，可选范围0-65535，http默认为80，https默认为443。</p>
</li>
<li><p>path（查找路径）：用来表示主机上的一个目录或文件地址。</p>
</li>
<li><p>query（查询参数）：用于给<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5?fromModule=lemma_inlink">动态网页</a>（如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技术制作的网页）传递参数，可有多个参数，用“&amp;”符号隔开，每个参数的名和值用“=”符号隔开。</p>
</li>
<li><p>fragment（#锚点）：在 URI 的末尾通过 hash mark（#）作为 fragment 的开头，其中 # 不属于 fragment 的值。</p>
<figure class="highlight jsp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//www.baidu.com/index#wang18</span></span><br><span class="line"><span class="number">1.</span># 有别于 ?，? 后面的查询字符串会被网络请求带上服务器，而 fragment 不会被发送的服务器</span><br><span class="line"><span class="number">2.</span>fragment 的改变不会触发浏览器刷新页面，但是会生成浏览历史</span><br><span class="line"><span class="number">3.</span>fragment 会被浏览器根据文件媒体类型（MIME type）进行对应的处理</span><br><span class="line"><span class="number">4.</span>Google 的搜索引擎会忽略 # 及其后面的字符串。</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">针对<span class="number">1</span>，<span class="number">2</span>条特性，用于单页面应用跳转页面，修改 location.<span class="property">hash</span> 值，触发 hashchange 事件，<span class="variable constant_">JS</span> 处理对应的逻辑，改变页面 <span class="variable constant_">UI</span> 实现页面的跳转，并在浏览器中产生历史记录。</span><br><span class="line"><span class="variable constant_">HTML</span>锚点，页面中寻找wang18这个锚点，并将页面滚动到该锚点的位置， <span class="variable constant_">URI</span> 中是空的 fragment，则浏览器默认显示页面的最顶端。</span><br><span class="line">fragment 会被 <span class="title class_">Google</span> 搜索引擎忽略掉，不利于<span class="variable constant_">SEO</span>。<span class="title class_">Google</span> 给了一个方案，就是在 # 紧跟一个 ! ，这样<span class="title class_">Google</span> 搜索引擎就会将这个 <span class="variable constant_">URI</span> 进行转换，如<span class="attr">https</span>:<span class="comment">//www.baidu.com/index#wang18转换后就成为了 https://www.baidu.com/index.html?_escaped_fragment_=wang18</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="二、缓存"><a href="#二、缓存" class="headerlink" title="二、缓存"></a>二、缓存</h3><ul>
<li>浏览器每次发起请求，都会先在浏览器缓存中查找该请求的结果以及缓存标识</li>
<li>浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中</li>
</ul>
<p><img src="https://pic.imgdb.cn/item/64108a80ebf10e5d53a39216.png"></p>
<blockquote>
<p>强制缓存</p>
</blockquote>
<p>强制缓存就是向浏览器缓存查找该请求结果，并根据该结果的缓存规则来决定是否使用该缓存结果的过程</p>
<ul>
<li>不存在该缓存结果和缓存标识，强制缓存失效，则直接向服务器发起请求</li>
<li>存在该缓存结果和缓存标识，但该结果已失效，强制缓存失效，则使用协商缓存(暂不分析)</li>
<li>存在该缓存结果和缓存标识，且该结果尚未失效，强制缓存生效，直接返回该结果</li>
</ul>
<blockquote>
<p>强制缓存的缓存规则是什么？</p>
</blockquote>
<p>当浏览器向服务器发起请求时，服务器会将缓存规则放入HTTP响应报文的HTTP头中和请求结果一起返回给浏览器，控制强制缓存的字段分别是Expires和Cache-Control，其中Cache-Control优先级比Expires高。</p>
<p>Expires是HTTP/1.0控制网页缓存的字段，其值为服务器返回该请求结果缓存的到期时间，即再次发起该请求时，如果客户端的时间小于Expires的值时，直接使用缓存结果。</p>
<p>在HTTP/1.1中，Cache-Control是最重要的规则，主要用于控制网页缓存，主要取值为：</p>
<ul>
<li>public：所有内容都将被缓存（客户端和代理服务器都可缓存）</li>
<li>private：所有内容只有客户端可以缓存，Cache-Control的默认取值</li>
<li>no-cache：客户端缓存内容，但是是否使用缓存则需要经过协商缓存来验证决定</li>
<li>no-store：所有内容都不会被缓存，即不使用强制缓存，也不使用协商缓存</li>
<li>max-age=xxx (xxx is numeric)：缓存内容将在xxx秒后失效</li>
</ul>
<blockquote>
<p>内存缓存和硬盘缓存</p>
</blockquote>
<p>内存缓存(from memory cache)和硬盘缓存(from disk cache)，如下:</p>
<ul>
<li>内存缓存(from memory cache)：内存缓存具有两个特点，分别是快速读取和时效性：</li>
<li>快速读取：内存缓存会将编译解析后的文件，直接存入该进程的内存中，占据该进程一定的内存资源，以方便下次运行使用时的快速读取。</li>
<li>时效性：一旦该进程关闭，则该进程的内存则会清空。</li>
<li>硬盘缓存(from disk cache)：硬盘缓存则是直接将缓存写入硬盘文件中，读取缓存需要对该缓存存放的硬盘文件进行I/O操作，然后重新解析该缓存内容，读取复杂，速度比内存缓存慢。</li>
</ul>
<p>在浏览器中，浏览器会在js和图片等文件解析执行后直接存入内存缓存中，那么当刷新页面时只需直接从内存缓存中读取(from memory cache)；而css文件则会存入硬盘文件中，所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。</p>
<blockquote>
<p>协商缓存</p>
</blockquote>
<p>协商缓存就是强制缓存失效后，浏览器携带缓存标识向服务器发起请求，由服务器根据缓存标识决定是否使用缓存的过程，主要有以下两种情况：</p>
<ul>
<li><p>协商缓存生效，返回304</p>
</li>
<li><p>协商缓存失效，返回200和请求结果结果</p>
</li>
</ul>
<blockquote>
<p>总结</p>
</blockquote>
<p>强制缓存优先于协商缓存进行，若强制缓存(Expires和Cache-Control)生效则直接使用缓存，若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)，协商缓存由服务器决定是否使用缓存，若协商缓存失效，那么代表该请求的缓存失效，重新获取请求结果，再存入浏览器缓存中；生效则返回304，继续使用缓存。</p>
<h3 id="三、DNS解析"><a href="#三、DNS解析" class="headerlink" title="三、DNS解析"></a>三、DNS解析</h3><blockquote>
<p>为什么需要DNS系统</p>
</blockquote>
<p>当客户端访问<a href="www.baidu.com">www.baidu.com</a>时计算机是识别不了的，需要转换成IP地址，计算机找到IP就能访问到web，就可以访问到对应的百度服务器。win+R输入cmd，输入ping<a href="www.baidu.com">www.baidu.com</a>可以看到对应的IP地址为112.80.248.76。</p>
<p>更多内容可以查看<a target="_blank" rel="noopener" href="https://blog.csdn.net/L2111533547/article/details/124180225">DNS域名解析CSDN博客</a></p>
<h3 id="四、TCP链接"><a href="#四、TCP链接" class="headerlink" title="四、TCP链接"></a>四、TCP链接</h3><p>传输控制协议（TCP，Transmission Control Protocol）是为了在不可靠的<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E4%BA%92%E8%81%94%E7%BD%91%E7%BB%9C/6908194?fromModule=lemma_inlink">互联网络</a>上提供可靠的<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E7%AB%AF%E5%88%B0%E7%AB%AF/8851783?fromModule=lemma_inlink">端到端</a>字节流而专门设计的一个<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE/8048821?fromModule=lemma_inlink">传输协议</a>。</p>
<p><img src="https://pic.imgdb.cn/item/6411dc39ebf10e5d53ee7408.png"></p>
<h3 id="五、发送HTTP请求"><a href="#五、发送HTTP请求" class="headerlink" title="五、发送HTTP请求"></a>五、发送HTTP请求</h3><p>指从<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E5%AE%A2%E6%88%B7%E7%AB%AF?fromModule=lemma_inlink">客户端</a>到<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF/3369401?fromModule=lemma_inlink">服务器端</a>的请求消息。HTTPS由两部分组成HTTP+SSL/TLS，在http上加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS加密，传输的数据自然也是加密后的数据。</p>
<p>HTTP协议：<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE">超文本传输协议</a>（HTTP，HyperText Transfer Protocol)是<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E4%BA%92%E8%81%94%E7%BD%91">互联网</a>上应用最为广泛的一种<a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE">网络协议</a>。</p>
<p>HTTPS=HTTP+加密+认证+完整性保护</p>
<p>发送http请求会对TCP连接进行处理，对HTTP协议进行解析，并按照报文格式进一步封装成HTTP Request对象。</p>
<p>Web服务器有Tomcat, Nginx和Apach</p>
<p><code>http请求报文：请求行，请求头，空行，请求数据</code></p>
<blockquote>
<p>请求行</p>
</blockquote>
<p>请求行由请求方法、URL和HTTP协议版本3个字段组成，它们用空格分隔。比如 GET /data/info.html HTTP/1.1</p>
<p>方法字段就是HTTP使用的请求方法，比如常见的GET/POST</p>
<p>其中HTTP协议版本有两种：HTTP1.0/HTTP1.1 可以这样区别：</p>
<p>HTTP1.0对于每个连接都只能传送一个请求和响应，请求就会关闭，HTTP1.0没有Host字段；而HTTP1.1在同一个连接中可以传送多个请求和响应，多个请求可以重叠和同时进行，HTTP1.1必须有Host字段。</p>
<blockquote>
<p>请求头</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">HTTP Request Header 请求头</span><br><span class="line">Accept：指定客户端能够接收的内容类型。</span><br><span class="line">Accept-Charset：浏览器可以接受的字符编码集。</span><br><span class="line">Accept-Encoding：指定浏览器可以支持的web服务器返回内容压缩编码类型。</span><br><span class="line">Accept-Language：浏览器可接受的语言。</span><br><span class="line">Accept-Ranges：可以请求网页实体的一个或者多个子范围字段。</span><br><span class="line">AuthorizationHTTP：授权的授权证书。</span><br><span class="line">Cache-Control：指定请求和响应遵循的缓存机制。</span><br><span class="line">Connection：表示是否需要持久连接。（HTTP 1.1默认进行持久连接）</span><br><span class="line">CookieHTTP：请求发送时，会把保存在该请求域名下的所有cookie值一起发送给web服务器。</span><br><span class="line">Content-Length：请求的内容长度。</span><br><span class="line">Content-Type：请求的与实体对应的MIME信息。</span><br><span class="line">Date：请求发送的日期和时间。</span><br><span class="line">Expect：请求的特定的服务器行为。</span><br><span class="line">From：发出请求的用户的Email。</span><br><span class="line">Host：指定请求的服务器的域名和端口号。</span><br><span class="line">If-Match：只有请求内容与实体相匹配才有效。</span><br><span class="line">If-Modified-Since：如果请求的部分在指定时间之后被修改则请求成功，未被修改则返回304代码。</span><br><span class="line">If-None-Match：如果内容未改变返回304代码，参数为服务器先前发送的Etag，与服务器回应的Etag比较判断是否改变。</span><br><span class="line">If-Range：如果实体未改变，服务器发送客户端丢失的部分，否则发送整个实体。</span><br><span class="line">If-Unmodified-Since：只在实体在指定时间之后未被修改才请求成功。</span><br><span class="line">Max-Forwards：限制信息通过代理和网关传送的时间。</span><br><span class="line">Pragma：用来包含实现特定的指令。</span><br><span class="line">Proxy-Authorization：连接到代理的授权证书。</span><br><span class="line">Range：只请求实体的一部分，指定范围。</span><br><span class="line">Referer：先前网页的地址，当前请求网页紧随其后,即来路。</span><br><span class="line">TE：客户端愿意接受的传输编码，并通知服务器接受接受尾加头信息。</span><br><span class="line">Upgrade：向服务器指定某种传输协议以便服务器进行转换（如果支持。</span><br><span class="line">User-AgentUser-Agent：的内容包含发出请求的用户信息。</span><br><span class="line">Via：通知中间网关或代理服务器地址，通信协议。</span><br><span class="line">Warning：关于消息实体的警告信息</span><br></pre></td></tr></table></figure>

<blockquote>
<p>空行</p>
</blockquote>
<p>作用是通过一个空行，告诉服务器请求头部到此为止。</p>
<blockquote>
<p>请求数据</p>
</blockquote>
<p>若方法字段是GET，参数直接置于请求行URL中，报文体则为空</p>
<p>若方法字段是POST，则通常来说此处放置的就是要提交的数据</p>
<blockquote>
<p>请求方式</p>
</blockquote>
<table>
<thead>
<tr>
<th align="center">请求方式</th>
<th align="center">描述</th>
</tr>
</thead>
<tbody><tr>
<td align="center">GET</td>
<td align="center">请求指定的页面信息，并返回实体主体</td>
</tr>
<tr>
<td align="center">POST</td>
<td align="center">向指定资源提交数据进行处理请求（例如提交表单或者上传文件）。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改</td>
</tr>
<tr>
<td align="center">PUT</td>
<td align="center">从客户端向服务器传送的数据取代指定的文档的内容</td>
</tr>
<tr>
<td align="center">DELETE</td>
<td align="center">请求服务器删除指定的页面</td>
</tr>
<tr>
<td align="center">OPTIONS</td>
<td align="center">允许客户端查看服务器的性能</td>
</tr>
<tr>
<td align="center">HEAD</td>
<td align="center">类似于get请求，只不过返回的响应中没有具体的内容，用于获取报头</td>
</tr>
<tr>
<td align="center">CONNECT</td>
<td align="center">HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器</td>
</tr>
<tr>
<td align="center">TRACE</td>
<td align="center">回显服务器收到的请求，主要用于测试或诊断</td>
</tr>
</tbody></table>
<h3 id="六、浏览器接收响应"><a href="#六、浏览器接收响应" class="headerlink" title="六、浏览器接收响应"></a>六、浏览器接收响应</h3><p><code>http响应报文：状态码、响应头、响应报文</code></p>
<blockquote>
<p>状态码</p>
</blockquote>
<p>常见状态码：200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1xx：指示信息–表示请求已接收，继续处理。</span><br><span class="line">2xx：成功–表示请求已被成功接收、理解、接受。</span><br><span class="line">3xx：重定向–要完成请求必须进行更进一步的操作。</span><br><span class="line">4xx：客户端错误–请求有语法错误或请求无法实现。</span><br><span class="line">5xx：服务器端错误–服务器未能实现合法的请求</span><br></pre></td></tr></table></figure>

<blockquote>
<p>响应头</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">HTTP Responses Header 响应头</span><br><span class="line">Accept-Ranges：表明服务器是否支持指定范围请求及哪种类型的分段请求。</span><br><span class="line">Age：从原始服务器到代理缓存形成的估算时间（以秒计，非负）。</span><br><span class="line">Allow：对某网络资源的有效的请求行为，不允许则返回405。</span><br><span class="line">Cache-Control：告诉所有的缓存机制是否可以缓存及哪种类型。</span><br><span class="line">Content-Encodingweb：服务器支持的返回内容压缩编码类型。</span><br><span class="line">Content-Language：响应体的语言。</span><br><span class="line">Content-Length：响应体的长度。</span><br><span class="line">Content-Location：请求资源可替代的备用的另一地址。</span><br><span class="line">Content-MD5：返回资源的MD5校验值。</span><br><span class="line">Content-Range：在整个返回体中本部分的字节位置。</span><br><span class="line">Content-Type：返回内容的MIME类型。</span><br><span class="line">Date：原始服务器消息发出的时间。</span><br><span class="line">ETag：请求变量的实体标签的当前值。</span><br><span class="line">Expires：响应过期的日期和时间。</span><br><span class="line">Last-Modified：请求资源的最后修改时间。</span><br><span class="line">Location：用来重定向接收方到非请求URL的位置来完成请求或标识新的资源。</span><br><span class="line">Pragma：包括实现特定的指令，它可应用到响应链上的任何接收方。</span><br><span class="line">Proxy-Authenticate：它指出认证方案和可应用到代理的该URL上的参数。</span><br><span class="line">refresh：应用于重定向或一个新的资源被创造，在5秒之后重定向（由网景提出，被大部分浏览器支持）</span><br><span class="line">Retry-After：如果实体暂时不可取，通知客户端在指定时间之后再次尝试。</span><br><span class="line">Serverweb：服务器软件名称。</span><br><span class="line">Set-Cookie：设置Http Cookie。</span><br><span class="line">Trailer：指出头域在分块传输编码的尾部存在。</span><br><span class="line">Transfer-Encoding：文件传输编码。</span><br><span class="line">Vary：告诉下游代理是使用缓存响应还是从原始服务器请求。</span><br><span class="line">Via：告知代理客户端响应是通过哪里发送的。</span><br><span class="line">Warning：警告实体可能存在的问题。</span><br><span class="line">WWW-Authenticate：表明客户端请求实体应该使用的授权方案。</span><br></pre></td></tr></table></figure>

<blockquote>
<p>响应报文</p>
</blockquote>
<p>响应报文就是响应的消息体，如果是纯数据就是返回纯数据，如果请求的是HTML页面，那么返回的就是HTML代码，如果是JS就是JS代码</p>
<h3 id="七、浏览器解析渲染页面"><a href="#七、浏览器解析渲染页面" class="headerlink" title="七、浏览器解析渲染页面"></a>七、浏览器解析渲染页面</h3><p>浏览器解析渲染页面是一个从上到下的过程。<br> 1.解析HTML标签，构建DOM树 。<br> 2.解析CSS，构建CSSOM树。<br> 3.把DOM和CSSOM组合成渲染树（render tree）。<br> 4.在渲染树的基础上进行布局，计算每个节点的几何结构。<br> 5.把每个节点绘制到屏幕上（painting）。</p>
<p>在构建页面的过程中，不可避免地会遇到浏览器要重新计算每个元素的大小位置样式。这里会遇到reflow和repaint。<br> <strong>Reflow</strong>（回流）Relayout（重新布局）<br> 重新计算元素的几何尺寸，位置。<br> 假设通过JS或是别的什么方法把一些元素消除了，浏览器又要重新计算每个元素的位置，渲染树，几何结构。</p>
<p><strong>Repaint</strong>（重绘）<br> 重新绘制界面发生变化的部分。<br> 通过JS修改元素的颜色，其他元素的几何结构位置没变。<br> 只是要改变样式颜色。重绘。</p>
<p>要尽量减少这两个东西的发生。尽量一次性修改样式，给动画使用绝对定位可以减少reflow次数，DOM离线后修改。都是可行的办法。</p>
<p>由于会发生 阻塞解析和阻塞渲染，还是尽量让CSSlink样式表存在于head标签内，JS的加载使用无顺序的async异步加载或者有顺序的defer加载方式。</p>
 
      <!-- reward -->
      
      <div id="reword-out">
        <div id="reward-btn">
          Donate
        </div>
      </div>
      
    </div>
    

    <!-- copyright -->
    
    <div class="declare">
      <ul class="post-copyright">
        <li>
          <i class="ri-copyright-line"></i>
          <strong>Copyright： </strong>
          
          Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
          
        </li>
      </ul>
    </div>
    
    <footer class="article-footer">
       
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95/" rel="tag">前端面试</a></li></ul>

    </footer>
  </div>

   
  <nav class="article-nav">
    
    
      <a href="/2020/07/21/page5/" class="article-nav-link">
        <strong class="article-nav-caption">下一篇</strong>
        <div class="article-nav-title">文字排版神器 一分钟了解markdown</div>
      </a>
    
  </nav>

  
   
    
    <script src="https://cdn.staticfile.org/twikoo/1.4.18/twikoo.all.min.js"></script>
    <div id="twikoo" class="twikoo"></div>
    <script>
        twikoo.init({
            envId: ""
        })
    </script>
 
</article>

</section>
      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2019-2023
        <i class="ri-heart-fill heart_icon"></i> 飞蓬
      </li>
    </ul>
    <ul>
      <li>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>Visitors:<span id="busuanzi_value_site_uv"></span></span>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>Views:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
        <script type="text/javascript" src='https://s9.cnzz.com/z_stat.php?id=1278069914&amp;web_id=1278069914'></script>
        
      </li>
    </ul>
  </div>
</footer>    
    </main>
    <div class="float_btns">
      <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

    </div>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/title.jpg" alt="飞蓬"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/about">关于我</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/404">公益404</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="Search">
        <i class="ri-search-line"></i>
      </a>
      
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i>请我喝杯咖啡吧~</p>
  <div class="reward-box">
    
    <div class="reward-item">
      <img class="reward-img" src="/images/alipay.jpg">
      <span class="reward-type">支付宝</span>
    </div>
    
    
    <div class="reward-item">
      <img class="reward-img" src="/images/wechat.jpg">
      <span class="reward-type">微信</span>
    </div>
    
  </div>
</div>
    
<script src="/js/jquery-3.6.0.min.js"></script>
 
<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->
 
<script src="/js/tocbot.min.js"></script>

<script>
  tocbot.init({
    tocSelector: ".tocbot",
    contentSelector: ".article-entry",
    headingSelector: "h1, h2, h3, h4, h5, h6",
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer: "main",
    positionFixedSelector: ".tocbot",
    positionFixedClass: "is-position-fixed",
    fixedSidebarOffset: "auto",
  });
</script>

<script src="https://cdn.staticfile.org/jquery-modal/0.9.2/jquery.modal.min.js"></script>
<link
  rel="stylesheet"
  href="https://cdn.staticfile.org/jquery-modal/0.9.2/jquery.modal.min.css"
/>
<script src="https://cdn.staticfile.org/justifiedGallery/3.8.1/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->
 <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.staticfile.org/photoswipe/4.1.3/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.staticfile.org/photoswipe/4.1.3/default-skin/default-skin.min.css">
<script src="https://cdn.staticfile.org/photoswipe/4.1.3/photoswipe.min.js"></script>
<script src="https://cdn.staticfile.org/photoswipe/4.1.3/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script> 
<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->
 
<script src="/js/busuanzi-2.3.pure.min.js"></script>
 
<!-- ClickLove -->
 
<script src="/js/clickLove.js"></script>
 
<!-- ClickBoom1 -->

<!-- ClickBoom2 -->

<!-- CodeCopy -->
 
<link rel="stylesheet" href="/css/clipboard.css">
 <script src="https://cdn.staticfile.org/clipboard.js/2.0.10/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>
 
<!-- CanvasBackground -->
 
<script src="/js/dz.js"></script>
 
<script>
  if (window.mermaid) {
    mermaid.initialize({ theme: "forest" });
  }
</script>


    
    

  </div>
</body>

</html>